/**
 * 单例模式
 */
//  单例模式非常常见，某个对象全局只需要一个实例时，就可以使用单例模式。它的优点也显而易见：
//  1. 它能够避免对象重复创建，节约空间并提升效率
//  2. 避免由于操作不同实例导致的逻辑错误

// 单例模式有两种实现方式：饿汉式和懒汉式。

// 一般的建议是：对于构建不复杂，加载完成后会立即使用的单例对象，推荐使用饿汉式。对于构建过程耗时较长，并不是所有使用此类都会用到的单例对象，推荐使用懒汉式。

// 饿汉式
class Singleton {
    private static instance = new Singleton();
    // 私有 构造函数
    private constructor() {}
    static getInstance() {
        return this.instance;
    }
}
// 我们将构造方法定义为 private，这就保证了其他类无法实例化此类，必须通过 getInstance 方法才能获取到唯一的 instance 实例

// 但饿汉式有一个弊端，那就是即使这个单例不需要使用，它也会在类加载之后立即创建出来，占用一块内存，并增加类初始化时间。
// 就好比一个电工在修理灯泡时，先把所有工具拿出来，不管是不是所有的工具都用得上。就像一个饥不择食的饿汉，所以称之为饿汉式。

// 懒汉式
class Singleton2 {
    private static instance: Singleton2;
    private constructor() {}
    static getInstance() {
        if (this.instance == null) {
            this.instance = new Singleton2();
        }
        return this.instance;
    }
}

// 使用静态内部类实现懒加载
class Singleton3 {
    // 静态内部类
    private static SingletonHolder = class {
        static instance = new Singleton3();
    };
    private constructor() {}
    public static getInstance() {
        return this.SingletonHolder.instance;
    }
}
console.log(Singleton3.getInstance());

// 懒加载方式在平时非常常见，比如打开我们常用的美团、饿了么、支付宝 app，应用首页会立刻刷新出来，
// 但其他标签页在我们点击到时才会刷新。这样就减少了流量消耗，并缩短了程序启动时间。再比如游戏中的某些模块，
// 当我们点击到时才会去下载资源，而不是事先将所有资源都先下载下来，这也属于懒加载方式，避免了内存浪费。

// 但懒汉式的缺点就是将程序加载时间从启动时延后到了运行时，虽然启动时间缩短了
// ，但我们浏览页面时就会看到数据的 loading 过程。如果用饿汉式将页面提前加载好，
// 我们浏览时就会特别的顺畅，也不失为一个好的用户体验。比如我们常用的 QQ、微信 app，
// 作为即时通讯的工具软件，它们会在启动时立即刷新所有的数据，保证用户看到最新最全的内容。
// 著名的软件大师 Martin 在《代码整洁之道》一书中也说到：不提倡使用懒加载方式，
// 因为程序应该将构建与使用分离，达到解耦。饿汉式在声明时直接初始化变量的方式也更直观易懂。所以在使用饿汉式还是懒汉式时，需要权衡利弊。
